//
//  ZTData.m
//  YSSmartHome
//
//  Created by Yahaong on 16/8/11.
//  Copyright © 2016年 yahaong. All rights reserved.
//

#import "DataManager.h"
#import "ZTDevice.h"
#import "XAIGateway.h"
#import "ZTLinkage.h"
#import "Friend.h"
#import <pthread.h>

static DataManager *manager;

@interface DataManager()
{
    pthread_mutex_t _devlistLock;
    pthread_mutex_t _gatewaylistLock;
    pthread_mutex_t _linkagelistLock;
    pthread_mutex_t _friendlistLock;
    pthread_mutex_t _roomlistLock;
    pthread_mutex_t _historyOperationLock;
}
@property (nonatomic, strong) NSMutableArray* cameraList;
@property (nonatomic, strong) NSMutableArray* gatewayListenList;
@property (nonatomic, strong) NSMutableArray* deviceListenList;
@property (nonatomic, strong) NSMutableArray* friendListenList;
@property (nonatomic, strong) NSMutableArray* linkageListenList;
@property (nonatomic, strong) NSMutableArray* bindGateModels;
@property (nonatomic, strong) NSMutableArray <NSNumber *> * joinDevListenList;
@property (nonatomic, strong) NSMutableArray* deviceRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* gatewayRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* friendRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* linkageRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* imMessageRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* deviceHistoryRefreshDelegates;
@property (nonatomic, strong) NSMutableArray* newJoinDelegates;
@property (nonatomic, strong) NSMutableArray* operationList;
@end

@implementation DataManager

- (void)dealloc {
    pthread_mutex_destroy(&_devlistLock);
    pthread_mutex_destroy(&_gatewaylistLock);
    pthread_mutex_destroy(&_linkagelistLock);
    pthread_mutex_destroy(&_friendlistLock);
    pthread_mutex_destroy(&_roomlistLock);
    pthread_mutex_destroy(&_historyOperationLock);
}

+ (instancetype)sharedManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc]init];
    });
    return manager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        pthread_mutex_init(&_devlistLock, NULL);
        pthread_mutex_init(&_gatewaylistLock, NULL);
        pthread_mutex_init(&_linkagelistLock, NULL);
        pthread_mutex_init(&_friendlistLock, NULL);
        pthread_mutex_init(&_roomlistLock, NULL);
        pthread_mutex_init(&_historyOperationLock, NULL);
    }
    return self;
}

#pragma mark - 回调 

- (void)linkageCallBack {
    for (int i = 0 ; i < [self.linkageRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.linkageRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(linkageRefresh:)]) {
            [aDeg linkageRefresh:self];
        }
    }
}

- (void)imMessageCallBack {
    for (int i = 0 ; i < [self.imMessageRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.imMessageRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(imMessageRefresh:)]) {
            [aDeg imMessageRefresh:self];
        }
    }
}

- (void)newJoinDevCallBack {
    for (int i = 0 ; i < [self.newJoinDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.newJoinDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(newJoinRefresh:)]) {
            [aDeg newJoinRefresh:self];
        }
    }
}

- (void)deviceHistoryOperationCallBack:(XAITYPEAPSN)apsn luid:(XAITYPELUID)luid {
    @synchronized (self.deviceHistoryRefreshDelegates) {
        for (int i = 0 ; i < [self.deviceHistoryRefreshDelegates count]; i++) {
            id<DataManagerRefreshDelegate> aDeg = [self.deviceHistoryRefreshDelegates objectAtIndex:i];
            if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
                && [aDeg respondsToSelector:@selector(deviceHistoryOperationRefresh:apsn:luid:)]) {
                [aDeg deviceHistoryOperationRefresh:self apsn:apsn luid:luid];
            }
        }
    }
}

- (void)gatewayCallBack {
    for (int i = 0 ; i < [self.gatewayRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.gatewayRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(gatewayRefresh:)]) {
            [aDeg gatewayRefresh:self];
        }
    }
}

- (void)gatewayCallBackWithType:(GatewayCallbackType)type {
    for (int i = 0 ; i < [self.gatewayRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.gatewayRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(gatewayRefresh:callbackType:)]) {
            [aDeg gatewayRefresh:self callbackType:type];
        }
    }
}

- (void)deviceRefreshCallBackWithType:(DeviceCallbackType)callbackType {
    for (int i = 0 ; i < [self.deviceRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.deviceRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(deviceRefresh:callbackType:)]) {
            [aDeg deviceRefresh:self callbackType:callbackType];
        }
    }
}

- (void)friendRefreshCallBackWithType:(FriendCallbackType)callbackType {
    for (int i = 0 ; i < [self.friendRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.friendRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(friendRefresh:callbackType:)]) {
            [aDeg friendRefresh:self callbackType:callbackType];
        }
    }
}

- (void)callBack {
    for (int i = 0 ; i < [self.deviceRefreshDelegates count]; i++) {
        id<DataManagerRefreshDelegate> aDeg = [self.deviceRefreshDelegates objectAtIndex:i];
        if ([aDeg conformsToProtocol:@protocol(DataManagerRefreshDelegate)]
            && [aDeg respondsToSelector:@selector(dataRefresh:)]) {
            [aDeg dataRefresh:self];
        }
    }
}

#pragma mark - 其他

- (BOOL)deleteJoinDev:(NSNumber *)luid {
    @synchronized (self) {
        BOOL result = false;
        for (NSNumber *aluid in self.joinDevListenList) {
            if ([aluid isEqualToNumber:luid]) {
                [self.joinDevListenList removeObject:luid];
                result = true;
                break;
            }
        }
        return result;
    }
}
- (void)setUnJoinDevList:(NSNumber *)luid {
    BOOL isFind = false;
    @synchronized (self.joinDevListenList)
    {
        for (NSNumber *aluid in self.joinDevListenList)
        {
            if ([aluid isEqualToNumber:luid])
            {
                isFind = true;
                break;
            }
        }
        if (!isFind)
        {
            [self.joinDevListenList addObject:luid];
            [kDataManager newJoinDevCallBack];
        }
    }
}

#pragma mark - 增 代理

- (void) addGatewayRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.gatewayRefreshDelegates addObject:delegate];
}

- (void)addRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.deviceRefreshDelegates addObject:delegate];
}

- (void)addFriendRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.friendRefreshDelegates addObject:delegate];
}

- (void)addLinkageRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.linkageRefreshDelegates addObject:delegate];
}

- (void)addNewJoinRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.newJoinDelegates addObject:delegate];
}

- (void)addIMMessageRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.imMessageRefreshDelegates addObject:delegate];
}

- (void)addHistoryOperationRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.deviceHistoryRefreshDelegates addObject:delegate];
}


#pragma mark - 删代理

- (void)removeRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.deviceRefreshDelegates removeObject:delegate];
}

- (void) removeGatewayRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.gatewayRefreshDelegates removeObject:delegate];
}

- (void)removeFriendRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.friendRefreshDelegates removeObject:delegate];
}

- (void) removeLinkageRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.linkageRefreshDelegates removeObject:delegate];
}

- (void) removeNewJoinRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.newJoinDelegates removeObject:delegate];
}

- (void)removeHistoryOperationRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate {
    [self.deviceHistoryRefreshDelegates removeObject:delegate];
}

- (void)removeIMMessageRefreshDelegate:(id<DataManagerRefreshDelegate>)delegate
{
    [self.imMessageRefreshDelegates removeObject:delegate];
}


#pragma mark - 增 

- (void)addGateway:(XAIGateway *)gateway {
    XAIGateway* findGateway = nil;
    [self gatewaylistLock];
    for (XAIGateway *adev in self.gatewayListenList) {
        if (gateway.apsn == adev.apsn && gateway.luid == adev.luid) {
            findGateway = adev;
            break;
        }
    }
    if (!findGateway) {
         [self.gatewayListenList addObject:gateway];
    }
    [self gatewaylistUnlock];
}

- (void)addDevice:(ZTDevice *)device {
    ZTDevice* findDev = nil;
    [self devlistLock];
    for (ZTDevice *adev in self.deviceListenList) {
        if (device.luid == adev.luid && device.apsn == device.apsn) {
            findDev = adev;
            break;
        }
    }
    if (!findDev) {
        [self.deviceListenList addObject:device];
    }
    [self devlistUnlock];
}

- (void)addFriend:(Friend *)friend {
    Friend* findFriend = nil;
    [self friendlistLock];
    for (Friend *aFriend in self.friendListenList) {
        if ([aFriend.mobile isEqualToString:friend.mobile] && aFriend.apsn == friend.apsn) {
            findFriend = aFriend;
            break;
        }
    }
    if (!findFriend) {
        [self.friendListenList addObject:friend];
    }
    [self friendlistUnlock];
}


- (void)addLinkage:(ZTLinkage *)aLink {
    ZTLinkage *findLinkage = nil;
    [self linkagelistLock];
    for (ZTLinkage *linkage in self.linkageListenList) {
        if (aLink.num == linkage.num
            && aLink.gatewayApsn == linkage.gatewayApsn) {
            findLinkage = linkage;
            break;
        }
    }
    if (findLinkage) {
        [self.linkageListenList removeObject:findLinkage];
    }
    [self.linkageListenList addObject:aLink];
    [self linkagelistUnlock];
}

#pragma mark - 删

- (void)removeDeviceWithApsn:(XAITYPEAPSN)apsn  luid: (XAITYPELUID)luid {
    NSMutableArray* deleteArrays = [NSMutableArray array];
    [self devlistLock];
    for (ZTDevice *adev in self.deviceListenList) {
        if (adev.apsn == apsn && adev.luid == luid ) {
            [deleteArrays addObject:adev];
        }
    }
    [self.deviceListenList removeObjectsInArray:deleteArrays];
    [self devlistUnlock];
}

- (void)removeDeviceWithApsn:(XAITYPEAPSN)apsn {
    NSMutableArray* deleteArrays = [NSMutableArray array];
    [self devlistLock];
    for (ZTDevice *adev in self.deviceListenList) {
        if (adev.apsn == apsn) {
            [deleteArrays addObject:adev];
        }
    }
    [self.deviceListenList removeObjectsInArray:deleteArrays];
    [self devlistUnlock];
}

- (void)removeGatewayWithApsn:(XAITYPEAPSN)gatewayApsn {
    NSMutableArray* deleteArrays = [NSMutableArray array];
    [self gatewaylistLock];
    for (XAIGateway *adev in self.gatewayListenList)  {
        if (gatewayApsn== adev.apsn) {
            [deleteArrays addObject:adev];
            break;
        }
    }
    [self.gatewayListenList removeObjectsInArray:deleteArrays];
    [self gatewaylistUnlock];
}

- (void)removeFriendWithApsn:(XAITYPEAPSN)apsn mobile: (NSString*)mobile {
    XAITYPELUID luid = [XAI mobileToLuid:mobile];
    [self removeFriendWithApsn:apsn luid:luid];
}
- (void)removeFriendWithApsn:(XAITYPEAPSN)apsn luid: (XAITYPELUID)luid {
    NSMutableArray* deleteArrays = [NSMutableArray array];
    [self friendlistLock];
    for (XAIGateway *adev in self.friendListenList) {
        if (apsn == adev.apsn && luid == adev.luid) {
            [deleteArrays addObject:adev];
            break;
        }
    }
    [self.friendListenList removeObjectsInArray:deleteArrays];
    [self friendlistUnlock];
}

- (BOOL)removeLinkageWithApsn: (XAITYPEAPSN) gatewayApsn  linkID:(uint8_t)linkID {
    ZTLinkage *findLinkage = nil;
    [self linkagelistLock];
    for (ZTLinkage *aLink in self.linkageListenList) {
        if (aLink.num == linkID
            && aLink.gatewayApsn ==gatewayApsn) {
            findLinkage = aLink;
            break;
        }
    }
    if (findLinkage) {
        [self.linkageListenList removeObject:findLinkage];
    }
    [self linkagelistUnlock];
    return  findLinkage != nil;
}

- (void)removeLinkageWithApsn:(XAITYPEAPSN)gatewayApsn {
    NSMutableArray* deleteArrays = [NSMutableArray array];
    [self linkagelistLock];
    for (ZTLinkage *linkage in self.linkageListenList) {
        if (gatewayApsn == linkage.gatewayApsn) {
            [deleteArrays addObject:linkage];
        }
    }
    [self.linkageListenList removeObjectsInArray:deleteArrays];
    [self linkagelistUnlock];
}

#pragma mark - 查

- (ZTDevice * __nullable)fetchDeviceWithApsn:(XAITYPEAPSN)apsn luid: (XAITYPELUID)luid {
    ZTDevice *device = nil;
    [self devlistLock];
    for (ZTDevice *aDevice in kDataManager.deviceListenList) {
        if (aDevice.luid == luid && aDevice.apsn == apsn) {
            device = aDevice;
            break;
        }
    }
    [self devlistUnlock];
    return device;
}

- (NSString *__nullable)allDeviceName {
    NSMutableString *strAllDevice = [NSMutableString string];
    [self devlistLock];
    for (ZTDevice *device in self.deviceListenList) {
        if (device.name.length == 0
            || device.apsn != kMQTTSessionManager.currentUser.currentBindApsn) {
            continue;
        }
        if (device.devType == ZTDeviceTypeTwoWaySocket || device.devType == ZTDeviceTypeTwoWay0Switch || device.devType == ZTDeviceTypeTwoWaySwitch) {
            [strAllDevice appendFormat:@"%@1|%@2|",device.getDeviceName,device.getDeviceName];
        }else if (device.devType == ZTDeviceTypeThreeWaySocket || device.devType == ZTDeviceTypeThreeWay0Switch || device.devType == ZTDeviceTypeThreeWaySwitch) {
            [strAllDevice appendFormat:@"%@1|%@2|%@3|",device.getDeviceName,device.getDeviceName,device.getDeviceName];
        }else if (device.devType == ZTDeviceTypeFourWaySocket || device.devType == ZTDeviceTypeFourWay0Switch || device.devType == ZTDeviceTypeFourWaySwitch) {
            [strAllDevice appendFormat:@"%@1|%@2|%@3|%@4",device.getDeviceName,device.getDeviceName,device.getDeviceName,device.getDeviceName];
        }else {
            [strAllDevice appendFormat:@"%@|",device.getDeviceName];
        }
    }
    [self devlistUnlock];
    if (strAllDevice.length > 0) {
        return [strAllDevice substringToIndex:strAllDevice.length - 1];
    }
    return nil;
}

- (XAIGateway * __nullable)fetchGatewayWithApsn:(XAITYPEAPSN)apsn luid: (XAITYPELUID)luid {
    XAIGateway *gateway = nil;
    [self gatewaylistLock];
    for (XAIGateway *aGateway in kDataManager.gatewayListenList) {
        if (aGateway.luid == luid && aGateway.apsn == apsn) {
            gateway = aGateway;
            break;
        }
    }
    [self gatewaylistUnlock];
    return gateway;
}

- (Friend * __nullable)fetchFriendWithApsn:(XAITYPEAPSN)apsn luid: (XAITYPELUID)luid {
    Friend *friend = nil;
    [self friendlistLock];
    for (Friend *aFriend in kDataManager.friendListenList) {
        if (aFriend.luid == luid && aFriend.apsn == apsn) {
            friend = aFriend;
            break;
        }
    }
    [self friendlistUnlock];
    return friend;
}
+ (NSMutableArray*)roomNameLists {
    NSMutableArray* arrayRoomList = [NSMutableArray array];
    NSString *roomPath = [MQTTSessionManager roomListPath];
    NSArray *arrayRooms = [NSKeyedUnarchiver unarchiveObjectWithFile:roomPath];
    if (arrayRooms.count == 0) {
        arrayRoomList = [NSMutableArray arrayWithObjects:@"客厅",@"卧室", nil];
    } else  {
        arrayRoomList = [NSMutableArray arrayWithArray:arrayRooms];
    }
    return arrayRoomList;
}

#pragma mark - 加锁

- (void)devlistLock {
    pthread_mutex_lock(&_devlistLock);
}

- (void)gatewaylistLock {
    pthread_mutex_lock(&_gatewaylistLock);
}

- (void)linkagelistLock {
    pthread_mutex_lock(&_linkagelistLock);
}

- (void)friendlistLock {
    pthread_mutex_lock(&_friendlistLock);
}

- (void)roomlistLock {
    pthread_mutex_lock(&_roomlistLock);
}

- (void)historyOperationLock {
    pthread_mutex_lock(&_historyOperationLock);
}

#pragma mark - 减锁

- (void)devlistUnlock {
    pthread_mutex_unlock(&_devlistLock);
}

- (void)gatewaylistUnlock {
    pthread_mutex_unlock(&_gatewaylistLock);
}

- (void)linkagelistUnlock {
    pthread_mutex_unlock(&_linkagelistLock);
}

- (void)friendlistUnlock {
    pthread_mutex_unlock(&_friendlistLock);
}

- (void)roomlistUnlock {
    pthread_mutex_unlock(&_roomlistLock);
}

- (void)historyOperationUnlock {
    pthread_mutex_unlock(&_historyOperationLock);
}

#pragma mark - getters and setters
- (NSMutableArray *)deviceListenList {
    if (!_deviceListenList) {
        _deviceListenList = [[NSMutableArray alloc]init];
    }
    return _deviceListenList;
}

- (NSMutableArray *)friendListenList {
    if (!_friendListenList) {
        _friendListenList = [[NSMutableArray alloc]init];
    }
    return _friendListenList;
}

- (NSMutableArray <NSNumber *> *)joinDevListenList {
    if (!_joinDevListenList) {
        _joinDevListenList = [[NSMutableArray alloc]init];
    }
    return _joinDevListenList;
}

- (NSMutableArray *)deviceRefreshDelegates {
    if (!_deviceRefreshDelegates) {
        _deviceRefreshDelegates = [NSMutableArray array];
    }
    return _deviceRefreshDelegates;
}

- (NSMutableArray *)gatewayListenList {
    if (!_gatewayListenList) {
        _gatewayListenList = [NSMutableArray array];
    }
    return _gatewayListenList;
}

- (NSMutableArray *)gatewayRefreshDelegates {
    if (!_gatewayRefreshDelegates) {
        _gatewayRefreshDelegates = [NSMutableArray array];
    }
    return _gatewayRefreshDelegates;
}

- (NSMutableArray *)friendRefreshDelegates {
    if (!_friendRefreshDelegates) {
        _friendRefreshDelegates = [NSMutableArray array];
    }
    return _friendRefreshDelegates;
}

- (NSMutableArray *)linkageListenList {
    if (!_linkageListenList) {
        _linkageListenList = [NSMutableArray array];
    }
    return _linkageListenList;
}

- (NSMutableArray *)bindGateModels {
    if (!_bindGateModels) {
        _bindGateModels = [NSMutableArray array];
    }
    return _bindGateModels;

}

- (NSMutableArray *)linkageRefreshDelegates {
    if (!_linkageRefreshDelegates) {
        _linkageRefreshDelegates = [NSMutableArray array];
    }
    return _linkageRefreshDelegates;
}

- (NSMutableArray *)deviceHistoryRefreshDelegates {
    if (!_deviceHistoryRefreshDelegates) {
        _deviceHistoryRefreshDelegates = [NSMutableArray array];
    }
    return _deviceHistoryRefreshDelegates;
}

- (NSMutableArray * _Nonnull)newJoinDelegates {
    if (!_newJoinDelegates) {
        _newJoinDelegates = [NSMutableArray array];
    }
    return _newJoinDelegates;
}

- (NSMutableArray *)imMessageRefreshDelegates {
    if (!_imMessageRefreshDelegates) {
        _imMessageRefreshDelegates = [NSMutableArray array];
    }
    return _imMessageRefreshDelegates;
}

- (NSMutableArray *)operationList {
    if (!_operationList) {
        _operationList = [NSMutableArray array];
    }
    return _operationList;
}

@end
